﻿#ifndef VIDEOCONFIG_H
#define VIDEOCONFIG_H

#ifdef __cplusplus
extern "C"
{
#endif
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>

    #include <libavutil/avassert.h>
    #include <libavutil/channel_layout.h>
    #include <libavutil/opt.h>
    #include <libavutil/mathematics.h>
    #include <libavutil/timestamp.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #include <libavutil/pixfmt.h>
    #include <libswresample/swresample.h>
    #include "libavfilter/avfilter.h"
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include <libavutil/time.h>
    #include "libavutil/pixfmt.h"
    #include "libswscale/swscale.h"
    #include "libswresample/swresample.h"

    #include "libavutil/avassert.h"
    #include "libavutil/channel_layout.h"
    #include "libavutil/common.h"
    #include "libavutil/opt.h"

#ifdef __cplusplus
}
#endif

#include <QAbstractVideoSurface>
#include <QVideoProbe>
#include <QThread>
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include <QWaitCondition>
#include <QQueue>
#include <QCamera>
#include <QPen>
#include <QPainter>
#include <QRgb>
#include <QAudio>     //这五个是QT处理音频的库
#include <QAudioFormat>
#include <QAudioInput>
#include <QAudioOutput>
#include <QIODevice>
#include <QPlainTextEdit>
#include <QScrollBar>
#include <QString>
#include <QMessageBox>
#include <QEvent>
#include <QReadWriteLock>

//视频音频编码类全局参数配置
class AudioOuputConfiguration
{
public:
    /*音频相关*/
    QAudioDeviceInfo audio;
    QMutex  audio_encode_mutex;
    QQueue<QByteArray> audio_data_queue;
};
extern class AudioOuputConfiguration audio_output_config;


//队列里最大存放的数据
#define QUEUE_DATA_CNT 100

/**
 * brief:           视音频 AVPacket 队列，使用ffmpeg从文件中获取
 * author:
 * time:            2020-12-11
 */
class VideoAudioQueue
{
private:
    QReadWriteLock video_lock; //读写锁
    QReadWriteLock audio_lock; //读写锁
    QQueue<AVPacket> video; //视频数据
    QQueue<AVPacket> audio; //音频数据
public:
    VideoAudioQueue()
    {
        video.clear();
        video.clear();
    }

    //向队列里插入视频帧数据
    void write_video_pack(AVPacket data)
    {
        video_lock.lockForWrite();
        video.enqueue(data);
        video_lock.unlock();
    }

    //返回队列里的视频帧
    AVPacket read_video_pack()
    {
        AVPacket data;
        video_lock.tryLockForRead();
        //判断队列是否为空,有数据才取
        if(video.isEmpty()==false)
        {
            data=video.dequeue();
        }
        video_lock.unlock();
        return data;
    }

    //返回队列里剩余的视频帧数据数量
    int get_video_pack_cnt()
    {
        int data=-1;
        video_lock.tryLockForRead();
        data=video.count();
        video_lock.unlock();
        return data;
    }

    //清除队列里的视频帧数据
    void clear_all_video()
    {
        video_lock.lockForWrite();
        video.clear();
        video_lock.unlock();
    }

    //向队列里插入音频帧数据
    void write_audio_pack(AVPacket data)
    {
        audio_lock.lockForWrite();
        audio.enqueue(data);
        audio_lock.unlock();
    }

    //返回队列里的音频帧
    AVPacket read_audio_pack()
    {
        AVPacket data;
        audio_lock.tryLockForRead();
        //判断队列是否为空,有数据才取
        if(audio.isEmpty()==false)
        {
            data=audio.dequeue();
        }
        audio_lock.unlock();
        return data;
    }

    //返回队列里剩余的音频帧数据数量
    int get_audio_pack_cnt()
    {
        int data=-1;
        audio_lock.tryLockForRead();
        data=audio.count();
        audio_lock.unlock();
        return data;
    }

    //清除队列里的音频帧数据
    void clear_all_audio()
    {
        audio_lock.lockForWrite();
        audio.clear();
        audio_lock.unlock();
    }
};

struct DecodingRelated
{
    AVFormatContext* format_ctx;//解码上下文
    VideoAudioQueue videoAudioAVPacketQueue;
    AVCodec* audioCodec = Q_NULLPTR;
    AVCodec* videoCodec = Q_NULLPTR;
    AVStream* audioStream = Q_NULLPTR;
    AVStream* videoStream = Q_NULLPTR;
    int videoStreamIndex = -1;
    int audioStreamIndex = -1;
    double audio_clock; //当前音频时钟位置
    double video_clock; //当前视频时钟位置
};
/**
* @brief           运行状态
* @author          wq
* @time            2020-12-11
* @param
* @return          正常返回0
* @remarks
*/
enum runningStat
{
    PLAY_STOP               =   0,  //停止
    PLAY_RUNNING            =   1,  //运行
    PLAY_PAUSE              =   2,  //暂停
    PLAY_SEEK               =   3,  //跳转
    PLAY_FINISHED           =   4,  //播放完成，但是还没有将线程资源释放掉
};

struct PlayControl
{
    enum runningStat runningStat = PLAY_STOP;
    bool videoFileEnd = false;
};

struct DecodingThreadSyncFlag
{
    enum runningStat playerThreadStat;
    enum runningStat audioThreadStat;
    enum runningStat videoThreadStat;
};

struct PlayRelated
{
    quint64 videoAllTime = 0; //视频总时间
    quint64 videoPlayTime = 0;//当前时间
    quint64 videoSeekTime = 0;//跳转时间
    DecodingThreadSyncFlag threadSync;
    QSize imageDisplaySize = QSize(100, 200);
    struct PlayControl threadControl; //控制三个线程，三个线程标志位共用
};

#endif // VIDEOCONFIG_H
